/************************************************************************************************************************************************
 *   Copyright (C) 2008 by Denjs                                                                                                                *
 *   dplsoft@pisem.net                                                                                                                          *
 *   http://qdroid.berlios.de                                                                                                                   *
 * -----------------------------------------------------------------------                                                                      *
 *   This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or (at your option) any later version.                                      *
 *   This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.                                 *
 *   You should have received a copy of the GNU General Public License along with this program; if not, write to the                            *
 *   Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                                                  *
 * -------------------------------------------------------------------------------------------------------------------------------------------- *
 *     Эта программа является свободным программным обеспечением; вы можете распространять её и/или модифицировать в соответствии с лицензией   *
 *   GNU General Public License  (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU) версии 2.0 или более поздней - на ваш выбор.                         *
 *     Эта программа распространяется  в надежде что она будет вам полезна, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, подразумеваемых или явных; без обещаний *
 *   полезности или применимости в конкретных условиях. Вы используете  данное ПО на свой страх и риск и сами полностью несете                  *
 *   ответственность за последствия. См. GNU General Public License (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU).                                  *
 *     Вы должны получить копию GNU General Public License (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU)с данным ПО; Если этого не случилось,       *
 *   обратитесь в Фонд Свободного Программного Обеспечения :                                                                                    *
 *   Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                                                  *
 * -------------------------------------------------------------------------------------------------------------------------------------------  *
 * Замечания для территории России: в соответствии с ГК РФ часть 4, начиная использовать данную программу (исполняемые файлы или исходные       *
 * тексты) вы автоматически соглашаетесь с данной лицензией.
 ************************************************************************************************************************************************/

/* 

  UTF-8 russian encoded file
  v 2009.09.14_2130
*/
#include "stdInReader.h"

//---------------------------------------------------------------
stdInReader::stdInReader(QObject * parent)
	: QThread (parent)
 {
	inited=false;
	DebugLevel=0;

	stdInCashMode=false;
	stdin_ReadyRead=false;

 }

//---------------------------------------------------------------
int stdInReader::open(bool _needAllStreams)
 {
   if (inited) return 1;//already opened 
   if (DebugLevel>=4) qDebug()<<"CP:stdInReader::init()[0041]";
   inited=false;
   int rez = 0;
//   if (rez==0) 
	if (! stdIn.open(stdin, QIODevice::ReadOnly)) 	 rez = -rez-1;
//   if (rez==0) 
	if (! stdOut.open(stdout, QIODevice::WriteOnly))  rez = -rez-2;
//   if (rez==0) 
	if (! stdErr.open(stdout, QIODevice::WriteOnly))  rez = -rez-4;
   if ( (rez!=0) and (_needAllStreams==true) ) close(true);
     else { inited=true; emit stdReader_Opened(); };
   if (DebugLevel>=4) qDebug()<<"CP:stdInReader::init()[0050]::rez="<<rez;
 
   return rez;
 };

//---------------------------------------------------------------
void stdInReader::stop()
{
   this->terminate();
};

//---------------------------------------------------------------
int stdInReader::close(bool failedInit)
 {
   this->terminate();//если закрываем потоки, работать нет смысла
   if (DebugLevel>=4) qDebug()<<"CP:stdInReader::reset()[0055]";
   stdIn.close();
   stdOut.close();
   stdErr.close();
   inited=false;
   if (!failedInit)  emit stdReader_Closed();
   return 0;
 };

//-----------------------------------------------------
void stdInReader::run()
 {
   bool toExit=false;
   if (DebugLevel>=4) qDebug()<<"CP:stdInReader::run()[0066]";
	
    if (!inited) return;
    while ( (!toExit) and (stdIn.error()==0) )//enum... value QFile::NoError
      {
	/*/ while (stdIn.bytesAvailable()==0) //<------- ВНИМАНИЕ! так - НЕ работает... да) QT 4.5
			                    //почему-то пока не начнешь читать, размер буфера не обновится...
		this->msleep(1000);//10 раз в секунду проверять что там нам прислали... думаю достаточно
	/* - */
	data=stdIn.read(1); //тут "блокирующее чтение"... потому никаких sleep не надо
	if (stdIn.bytesAvailable()>0)
	   data.append(stdIn.read(stdIn.bytesAvailable()));//и только тут буфер покажет сколько нам послупило данных. лол)
	
	if (stdIn.error()!=0) {toExit=true; continue;};
	if (data.size()==0) {toExit=true; emit stdIn_StreamClosed(); break;};//если ничего не прочли... то вероятно поток закрыт... 
		//как например бывает при чтении "встроенного документа" из bash...
		//вываливаемся...
	//if (DebugLevel>=4) 
	//	qDebug()<<"CP:stdInReader::run()[0085]::stdIn.error()"<<stdIn.error();


        if (DebugLevel>=4) qDebug()<<"CP:stdInReader::run()[0080]:(processing in progress...)";
	//emit received_StdIn(data);
	from_stdin_buffer(data);//а там уже сами решат, что отсылать а что нет

	/*-/
	////------ далее - демо код для примера ----------
	//// что бы оно заработало - надо stdOut.open... раскомментировать выше...
		stdOut.write(QByteArray().append(QString("[")));
		stdOut.write(data);
		stdOut.write(QByteArray().append(QString("]")));
		stdOut.flush();//отправим сразу...
	/* - */
      };
    return;
 }
//интерфейсы для запуска есть: слот QTread::start(), terminate () 

//---------------------------------------------------------------
//:private:
void stdInReader::from_stdin_buffer(QByteArray Message)// -> к нему подключен SIGNAL QDroid.rsv_from_std_in
{
 if (DebugLevel>=4) qDebug()<<"CP:t_BaseBot::rsv_from_std_in()[0055]";
 if (stdInCashMode)
     { 
	if (stdInCash.size()>maxCashSize)
	   {
		emit stdIn_CashOverflow();
	   };
	stdInCash.append(Message); 
	stdin_ReadyRead=true;
	emit stdIn_readyRead(); 
     }
    else 
     {
	emit stdIn_received(Message);//перешлем его
    	stdin_ReadyRead=false;
     };
}

//-----------------------------------------------------
//сделать функции потокобезопасными!
//функция, не слот
QByteArray stdInReader::stdin_Read(int maxSize)// -> к нему подключен SIGNAL QDroid.rsv_from_std_in
{
	QByteArray baRez = stdInCash.left(maxSize);
	stdInCash=stdInCash.mid(maxSize);
	if (stdInCash.size()==0) stdin_ReadyRead=false;
		//пока есть данные - флаг должен быть выставлен
	return baRez;
}

//-----------------------------------------------------
int stdInReader::stdin_GetCashSize()// 
{
	return stdInCash.size();
}

//-----------------------------------------------------
//если "да" - то значит есть что читать.
// иначе - таймаут
bool stdInReader::sdtin_waitFirReadyRead(int maxTimeMs)// 
{
	bool rez=false;  //TIMER!!!!
	int countdown = maxTimeMs;

	//qDebug()<<"!:"<<countdown;
	if (stdInCashMode) return false;// не тот режим - всегда "нет"

	//qDebug()<<"!::"<<countdown;
	while (!stdin_ReadyRead)
	  {
		//QThread::msleep(100);
		sleepMS(100);
		//qDebug()<<"!:::"<<countdown;
		if (countdown<0) return rez;
		countdown=countdown-100;
		QApplication::processEvents();
	  };
	rez=stdin_ReadyRead;
	return rez;
}

//-----------------------------------------------------
//спим в millisecinds!
int stdInReader::sleepMS( unsigned int time)
{	
	// Linux:
	#if defined (Q_WS_X11) 
			usleep(time*1000);//sleep in millisecinds 
	// Win:
	#elif defined (Q_WS_WIN)
			Sleep(time);//WIN  2008.02.19
	// Mac:
	#elif defined (Q_WS_MAC)
			// NOT SUPPORTED THIS VERSION 
	#else
			// NOT SUPPORTED THIS VERSION 
	#endif
	return 0;
};

//-----------------------------------------------------
int stdInReader::send_StdOut(const QByteArray &_data)
  {
	if (DebugLevel>=4) qDebug()<<"CP:stdInReader::send_StdOut()[0096]";
	int rz=stdOut.write(_data);
	stdOut.flush();
	return rz;
  }

//-----------------------------------------------------
int stdInReader::send_StdErr(const QByteArray &_data)
  {
	if (DebugLevel>=4) qDebug()<<"CP:stdInReader::send_StdErr()[0106]";
	int rz=stdErr.write(_data);
	stdErr.flush();
	return rz;
  }
//---------------------------------------------------------------------
//установить режим кеширования для чтения потока данных
// по умолчанию -  DataFlow
void stdInReader::stdIn_SetCachedMode()
{
	stdInCashMode=true;
	emit stdIn_ChangedCashMode(stdInCashMode);
}
//---------------------------------------------------------------------
//установить режим кеширования для чтения потока данных
// по умолчанию -  DataFlow
void stdInReader::stdIn_SetDataFlowMode()
{
	stdInCashMode=false;
	emit stdIn_ChangedCashMode(stdInCashMode);
}